package com.platform.file.service.impl;

import com.platform.common.core.constant.ServiceNameConstants;
import com.platform.common.core.exception.ServiceException;
import com.platform.common.core.utils.DateUtils;
import com.platform.common.core.utils.file.FileUtils;
import com.platform.common.security.utils.AESUtil_SC;
import com.platform.common.security.utils.SecurityUtils;
import com.platform.file.constant.SysFileConstants;
import com.platform.file.domain.DicFileLog;
import com.platform.file.mapper.DicFileLogMapper;
import com.platform.file.service.IDicFileLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文件操作日志Service业务层处理
 *
 * @author platform
 * @date 2023-05-08
 */
@Slf4j
@Service
public class DicFileLogServiceImpl implements IDicFileLogService {
    @Resource
    private DicFileLogMapper dicFileLogMapper;

    @Override
    public DicFileLog selectDicFileLogById(Long id) {
        return dicFileLogMapper.selectDicFileLogById(id);
    }

    @Override
    public List<DicFileLog> selectDicFileLogList(DicFileLog dicFileLog) {
        return dicFileLogMapper.selectDicFileLogList(dicFileLog);
    }

    @Override
    public int insertDicFileLog(DicFileLog dicFileLog) {
        dicFileLog.setCreateTime(DateUtils.getNowDate());
        dicFileLog.setCreateBy(SecurityUtils.getUsername());
        return dicFileLogMapper.insertDicFileLog(dicFileLog);
    }

    @Override
    public int insertDicFileLogWithUserId(DicFileLog dicFileLog, Long userId) {
        dicFileLog.setCreateTime(DateUtils.getNowDate());
        dicFileLog.setCreateBy(SecurityUtils.getUsername());
        return dicFileLogMapper.insertDicFileLog(dicFileLog);
    }

    @Override
    public int updateDicFileLog(DicFileLog dicFileLog) {
        dicFileLog.setUpdateTime(DateUtils.getNowDate());
        return dicFileLogMapper.updateDicFileLog(dicFileLog);
    }

    @Override
    public int deleteDicFileLogByIds(Long[] ids) {
        return dicFileLogMapper.deleteDicFileLogByIds(ids);
    }

    @Override
    public int deleteDicFileLogById(Long id) {
        return dicFileLogMapper.deleteDicFileLogById(id);
    }

    @Override
    public void saveUploadLog(String serviceCode, MultipartFile file, String url) {
        DicFileLog fileLog = getFileLog(serviceCode, "", "", "", "");
        BigDecimal size = BigDecimal.valueOf(file.getSize());
        saveDicFileLog(url, size, fileLog);
    }

    @Override
    public void saveUploadLogWithUserId(String serviceCode, Long userId, MultipartFile file, String url) {
        DicFileLog fileLog = getFileLog(serviceCode, "", "", "", "");
        BigDecimal size = BigDecimal.valueOf(file.getSize());
        saveDicFileLog(url, size, fileLog);
    }

    @Override
    public void saveUploadLog(String serviceCode, String filePath, double reSize) {
        DicFileLog fileLog = new DicFileLog();
        fileLog.setServiceCode(serviceCode);
        if (serviceCode.equals(SysFileConstants.SERVICENAME_SYS)) {
            fileLog.setServiceName(SysFileConstants.SERVICENAME_SYS_CN);
        } else {
            fileLog.setServiceName(ServiceNameConstants.SERVICE_NAME_MAP.get(serviceCode));
        }
        saveDicFileLog(filePath, BigDecimal.valueOf(reSize), fileLog);
    }

    @Override
    public void saveSelectLog(String filePath) {
        DicFileLog dto = new DicFileLog();
        dto.setFileUrl(filePath);
        List<DicFileLog> fileLogList = this.selectDicFileLogList(dto);
        if (CollectionUtils.isNotEmpty(fileLogList) && fileLogList.size() > 0) {
            DicFileLog fileLog = fileLogList.get(0);
            fileLog.setFileStatus(SysFileConstants.FILE_STATUS_1);
            fileLog.setOperateTime(DateUtils.getNowDate());
            fileLog.setOperateType(SysFileConstants.FILE_OPERATE_2);
            this.insertDicFileLog(fileLog);
        }

    }

    @Override
    public void saveDeleteLog(String filePath) {
        DicFileLog dto = new DicFileLog();
        dto.setFileUrl(filePath);
        List<DicFileLog> fileLogList = this.selectDicFileLogList(dto);
        List<DicFileLog> dicFileLogList = fileLogList.stream().filter(a -> filePath.equals(a.getFileUrl())).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(dicFileLogList) && dicFileLogList.size() > 0) {
            DicFileLog fileLog = dicFileLogList.get(0);
            fileLog.setFileStatus(SysFileConstants.FILE_STATUS_0);
            fileLog.setOperateTime(DateUtils.getNowDate());
            fileLog.setOperateType(SysFileConstants.FILE_OPERATE_0);
            this.insertDicFileLog(fileLog);

            //修改相同路径的文件状态
            List<Long> ids = dicFileLogList.stream().map(DicFileLog::getId).collect(Collectors.toList());
            dicFileLogMapper.updateStatusByIds(ids, SysFileConstants.FILE_STATUS_0);
        }

    }

    @Override
    public void saveUploadLogNew(String serviceCode, MultipartFile file, String url, String bucketName, String fileUrlSecret, String cataloguePrefix, String fileTag) {
        DicFileLog fileLog = getFileLog(serviceCode, bucketName, fileUrlSecret, cataloguePrefix, fileTag);
        BigDecimal size = BigDecimal.valueOf(file.getSize());
        saveDicFileLog(url, size, fileLog);
    }


    @Override
    public void saveUploadLogNew(String serviceCode, String filePath, double reSize, String bucketName, String fileUrlSecret, String cataloguePrefix, String fileTag) {
        DicFileLog fileLog = getFileLog(serviceCode, bucketName, fileUrlSecret, cataloguePrefix, fileTag);
        saveDicFileLog(filePath, BigDecimal.valueOf(reSize), fileLog);
    }

    private DicFileLog getFileLog(String serviceCode, String bucketName, String fileUrlSecret, String cataloguePrefix, String fileTag) {
        DicFileLog fileLog = new DicFileLog();
        fileLog.setServiceCode(serviceCode);
        fileLog.setBucketName(bucketName);
        fileLog.setFolder(cataloguePrefix);
        fileLog.setFileUrlSecret(fileUrlSecret);
        fileLog.setFileTag(fileTag);
        if (serviceCode.equals(SysFileConstants.SERVICENAME_SYS)) {
            fileLog.setServiceName(SysFileConstants.SERVICENAME_SYS_CN);
        } else {
            fileLog.setServiceName(ServiceNameConstants.SERVICE_NAME_MAP.get(serviceCode));
        }
        return fileLog;
    }

    private void saveDicFileLog(String filePath, BigDecimal size, DicFileLog fileLog) {
        fileLog.setFileName(FileUtils.getName(filePath));
        String contentType = getContentType(filePath);
        if (Objects.equals(contentType, "")) {
            fileLog.setFileType(null);
        } else {
            fileLog.setFileType(contentType);
        }
        BigDecimal fileSize = size.divide(new BigDecimal(1024), RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP);
        fileLog.setFileSize(fileSize);
        fileLog.setFileUrl(filePath);
        fileLog.setFileStatus(SysFileConstants.FILE_STATUS_1);
        fileLog.setOperateTime(DateUtils.getNowDate());
        fileLog.setOperateType(SysFileConstants.FILE_OPERATE_1);

        this.insertDicFileLog(fileLog);
    }

    @Override
    public DicFileLog selectDicFileLogByFileKey(String fileKey) {
        return dicFileLogMapper.selectDicFileLogByFileKey(fileKey);
    }

    @Override
    public void saveShareFile(String serviceName, String fileName, String fPath, String bucketName, String contentType, BigDecimal size, String fileKey) {
        DicFileLog dicFileLog = new DicFileLog();
        dicFileLog.setFileKey(fileKey);
        dicFileLog.setFolder(SysFileConstants.NO_PERMISSION);
        dicFileLog.setServiceCode(serviceName);
        dicFileLog.setServiceName(ServiceNameConstants.SERVICE_NAME_MAP.getOrDefault(serviceName, serviceName));
        dicFileLog.setFileName(fileName);
        dicFileLog.setFileType(contentType);
        dicFileLog.setFileSize(size.divide(new BigDecimal(1024), RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP));
        dicFileLog.setFileUrl(fPath);
        dicFileLog.setFileStatus(SysFileConstants.FILE_STATUS_1);
        dicFileLog.setOperateTime(new Date());
        dicFileLog.setOperateType(SysFileConstants.FILE_OPERATE_1);
        dicFileLog.setBucketName(bucketName);
        try {
            dicFileLog.setFileUrlSecret(AESUtil_SC.encryptNoBase64(bucketName + "/" + fPath, SysFileConstants.FILESECRET));
        } catch (Exception e) {
            log.error("文件路径加密异常,path:{}", bucketName + "/" + fPath, e);
            throw new ServiceException("文件路径加密异常");
        }
        dicFileLog.setCreateBy(Optional.ofNullable(SecurityUtils.getUsername()).orElse("SYS"));
        dicFileLog.setCreateTime(new Date());
        dicFileLogMapper.insertDicFileLog(dicFileLog);
    }

    public String getContentType(String fileName) {
        String contentType;

        String suffix = "";
        int idx;
        if ((idx = fileName.lastIndexOf(".")) > 0) {
            suffix = fileName.substring(idx + 1);
        }
        if ("".equals(suffix)) {
            return null;
        }
        switch (suffix) {
            case "jpg":
            case "jpeg":
                contentType = "image/jpeg";
                break;
            case "png":
                contentType = "image/png";
                break;
            case "txt":
                contentType = "text/plain";
                break;
            case "md":
            case "sql":
            case "xmind":
            case "lrc":
                contentType = "application/octet-stream";
                break;
            case "pdf":
                contentType = "application/pdf";
                break;
            case "docx":
            case "doc":
                contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                break;
            case "xls":
                contentType = "application/vnd.ms-excel";
                break;

            default:
                contentType = suffix;
        }
        return contentType;
    }
}
